package com.fjwt.gz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.bo.AwardUserTimesBO;
import com.fjwt.gz.db.dto.ScoreExchangeDTO;
import com.fjwt.gz.db.entity.AgentAppEntity;
import com.fjwt.gz.db.entity.AgentInfoEntity;
import com.fjwt.gz.db.entity.AgentScoreEntity;
import com.fjwt.gz.db.entity.AwardCouponEntity;
import com.fjwt.gz.db.entity.AwardGoodsEntity;
import com.fjwt.gz.db.entity.AwardVirtualEntity;
import com.fjwt.gz.db.entity.ExchangeBlacklistEntity;
import com.fjwt.gz.db.entity.ScoreExchangeEntity;
import com.fjwt.gz.db.vo.AgentAppVO;
import com.fjwt.gz.db.vo.ScoreExchangeFansVO;
import com.fjwt.gz.db.vo.ScoreExchangeRecordVO;
import com.fjwt.gz.db.vo.ScoreExchangeVO;
import com.fjwt.gz.service.mapper.ScoreExchangeMapper;
import com.fjwt.gz.util.PeriodUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 积分兑换表(积分商城表/权益商城表) 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class ScoreExchangeService extends ServiceImpl<ScoreExchangeMapper, ScoreExchangeEntity> {

    @Autowired
    private ScoreExchangeMapper scoreExchangeMapper;
    @Autowired
    private ExchangeBlacklistService exchangeBlacklistService;
    @Autowired
    private AgentInfoService agentInfoService;
    @Autowired
    private AwardCouponService awardCouponService;
    @Autowired
    private AwardGoodsService awardGoodsService;
    @Autowired
    private AwardVirtualService awardVirtualService;
    @Autowired
    private AgentAppService agentAppService;
    @Autowired
    private AgentScoreService agentScoreService;
    @Autowired
    private ActivityService activityService;

    /**
     * 获取积分商城列表
     *
     * @param page
     * @param scoreExchangeDTO
     * @return
     */
    public IPage<ScoreExchangeVO> queryList(IPage<?> page, ScoreExchangeDTO scoreExchangeDTO) {
        if (Constants.SYS_ROLE_TYPE.PROXY.equals(scoreExchangeDTO.getSysType()) && !checkIsProxy(scoreExchangeDTO)) {
            return new Page<>();
        }
        IPage<ScoreExchangeVO> scoreExchangeVOIPage = scoreExchangeMapper.queryList(page, scoreExchangeDTO);
        if (CS.SYS_ROLE_TYPE.MCH.equals(scoreExchangeDTO.getSysType()) && scoreExchangeDTO.getType() != null && 1 == scoreExchangeDTO.getType()) {
            for (ScoreExchangeVO record : scoreExchangeVOIPage.getRecords()) {
                // 卡券总次数限制
                if (record.getPeriodType() != 0) {
                    int currentPeriod = PeriodUtil.getPeriod(record.getPeriodType());
                    if (currentPeriod == record.getCurrentPeriodType()) {
                        record.setSyNum(record.getPeriodTimes() - record.getCurrentPeriodTimes());
                    } else {
                        record.setSyNum(record.getPeriodTimes());
                    }
                }
                // 用户卡券次数redis缓存key
                String awardCurrentTimesKey = String.format("%s:%s:%s:%s%s", Constants.REDIS_ACTIVITY.AWARD, record.getAwardType(), record.getAwardId(), Constants.REDIS_ACTIVITY.USER_FILENAME, scoreExchangeDTO.getFansId());
                AwardUserTimesBO awardUserTimesBO = RedisUtil.getObject(awardCurrentTimesKey, AwardUserTimesBO.class);
                if (record.getEveryonePeriodType() != 0) {
                    if (ObjectUtils.isNotEmpty(awardUserTimesBO)) {
                        record.setResidueTimes(record.getEveryonePeriodTimes() - awardUserTimesBO.getCurrentPeriodTimes());
                    } else {
                        record.setResidueTimes(record.getEveryonePeriodTimes());
                    }
                } else {
                    if (record.getEveryoneMaxNum() != 0) {
                        if (ObjectUtils.isNotEmpty(awardUserTimesBO)) {
                            record.setResidueTimes(record.getEveryoneMaxNum() - awardUserTimesBO.getTotalJoinTimes());
                        } else {
                            record.setResidueTimes(record.getEveryoneMaxNum());
                        }
                    }
                }
            }
        }
        return scoreExchangeVOIPage;
    }

    /**
     * 是否属于机构端
     *
     * @param scoreExchangeDTO
     * @return
     */
    private Boolean checkIsProxy(ScoreExchangeDTO scoreExchangeDTO) {
        List<AgentScoreEntity> list = agentScoreService.list(
                AgentScoreEntity.gw()
                        .eq(AgentScoreEntity::getAgentNo, scoreExchangeDTO.getCurrentCreatedAgentNo())
                        .eq(AgentScoreEntity::getIsDefault, 0));

        List<AgentAppEntity> agentAppList = agentAppService.list(
                AgentAppEntity.gw()
                        .eq(AgentAppEntity::getAgentNo, scoreExchangeDTO.getCurrentCreatedAgentNo())
                        .eq(AgentAppEntity::getType, Constants.AGENT_APP_TYPE.WX_LITE)
                        .eq(AgentAppEntity::getIsDeleted, Constants.IS_DELETED.NO)
                        .eq(AgentAppEntity::getIsDefault, 1)
        );
        if (ObjectUtil.isEmpty(list) || ObjectUtil.isEmpty(agentAppList)) {
            return false;
        }
        return true;
    }

    /**
     * 获取积分商城积分兑换明细
     */
    public IPage<ScoreExchangeFansVO> getScoreConsumeList(IPage page, ScoreExchangeDTO scoreExchangeDTO) {
        return scoreExchangeMapper.getScoreConsumeList(page, scoreExchangeDTO);
    }

    /**
     * 获取积分兑换明细
     */
    public IPage<ScoreExchangeFansVO> selectConsumeList(IPage page, ScoreExchangeDTO scoreExchangeDTO) {
        return scoreExchangeMapper.selectConsumeList(page, scoreExchangeDTO);
    }


    /**
     * 积分商城详情
     *
     * @param exchangeId
     * @param awardType
     * @return
     */
    public ScoreExchangeVO getDetails(Long exchangeId, String awardType) {
        if (Objects.isNull(exchangeId) || StringUtils.isEmpty(awardType)) {
            throw new BizException("网络故障，请稍后重试！");
        }
        return scoreExchangeMapper.getDetails(exchangeId, awardType);
    }

    /**
     * 保存积分商城
     *
     * @param scoreExchangeDTO
     * @return
     */
    @Transactional
    public void saveScoreExchange(ScoreExchangeDTO scoreExchangeDTO) {
        ScoreExchangeEntity one = getOne(
                ScoreExchangeEntity.gw().
                        eq(ScoreExchangeEntity::getAwardId, scoreExchangeDTO.getAwardId()).
                        eq(ScoreExchangeEntity::getAwardType, scoreExchangeDTO.getAwardType())
        );
        if (ObjectUtils.isNotEmpty(one)) {
            throw new BizException("当前奖品类型下的奖品已存在！");
        }

        AgentInfoEntity agentInfo = agentInfoService.getAgentInfo(scoreExchangeDTO.getAgentNo());
        if (ObjectUtils.isEmpty(agentInfo)) {
            throw new BizException("当前机构不存在！");
        }

        List<AgentAppVO> agentNoApp = agentAppService.getAgentNoApp(scoreExchangeDTO.getAgentNo(), Constants.AGENT_APP_TYPE.WX_LITE, scoreExchangeDTO.getAppId());
        if (ObjectUtils.isEmpty(agentNoApp)){
            throw new BizException("当前机构下的小程序不存在！");
        }

        if (Constants.AWARD.COUPON == scoreExchangeDTO.getAwardType()) {
            AwardCouponEntity awardCouponEntity = awardCouponService.getById(scoreExchangeDTO.getAwardId());
            if (!scoreExchangeDTO.getAgentNo().equals(awardCouponEntity.getAgentNo())) {
                throw new BizException("所选机构下下无此奖品，请排查！");
            }
            if (ObjectUtils.isNotEmpty(scoreExchangeDTO.getIsFlag()) && 2 == scoreExchangeDTO.getIsFlag()) {
                activityService.checkCouponThirdParam(awardCouponEntity);
            }
        }
        if (Constants.AWARD.GOODS == scoreExchangeDTO.getAwardType()) {
            AwardGoodsEntity awardGoodsEntity = awardGoodsService.getById(scoreExchangeDTO.getAwardId());
            if (!scoreExchangeDTO.getAgentNo().equals(awardGoodsEntity.getAgentNo())) {
                throw new BizException("所选机构下下无此奖品，请排查！");
            }
        }
        if (Constants.AWARD.VIRTUAL_COUPON == scoreExchangeDTO.getAwardType()) {
            AwardVirtualEntity awardVirtualEntity = awardVirtualService.getById(scoreExchangeDTO.getAwardId());
            if (!scoreExchangeDTO.getAgentNo().equals(awardVirtualEntity.getAgentNo())) {
                throw new BizException("所选机构下下无此奖品，请排查！");
            }
        }

        ScoreExchangeEntity entity = new ScoreExchangeEntity();
        BeanUtils.copyProperties(scoreExchangeDTO, entity);
        entity.setAgentNo1(agentInfo.getAgentNo1());
        entity.setAgentNo2(agentInfo.getAgentNo2());
        entity.setAgentNo3(agentInfo.getAgentNo3());
        entity.setAgentNo4(agentInfo.getAgentNo4());
        baseMapper.insert(entity);
        List<Long> ruleIdList = scoreExchangeDTO.getBlacklistRuleIdList();
        //是否开启黑名单
        if (CollUtil.isNotEmpty(ruleIdList) && entity.getHasBlacklist() == 1) {
            List<ExchangeBlacklistEntity> activityBlacklistEntityList = new ArrayList<>();
            for (Long ruleId : ruleIdList) {
                ExchangeBlacklistEntity exchangeBlacklistEntity = new ExchangeBlacklistEntity();
                exchangeBlacklistEntity.setScoreExchangeId(entity.getScoreExchangeId());
                exchangeBlacklistEntity.setBlacklistRuleId(ruleId);
                activityBlacklistEntityList.add(exchangeBlacklistEntity);
            }
            exchangeBlacklistService.saveBatch(activityBlacklistEntityList);
            log.info("黑名单限制表新增成功, {}", activityBlacklistEntityList);
        }
    }

    /**
     * 积分兑换明细导出Excel
     *
     * @param page
     * @param scoreExchangeDTO
     * @return
     */
    public void selectDeriveConsumeList(IPage page, ScoreExchangeDTO scoreExchangeDTO, HttpServletResponse response) throws Exception {
        // 设置分页参数，查询所有数据
        page.setSize(-1);
        List<ScoreExchangeFansVO> scoreExchangeFansVOIPage = scoreExchangeMapper.selectConsumeList(page, scoreExchangeDTO).getRecords();

        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("积分兑换明细" + ".xlsx", "UTF-8"));
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // sheet
        writer.renameSheet("积分兑换明细");
        writer.addHeaderAlias("name", "卡券名称");
        writer.addHeaderAlias("phone", "兑换人手机号");
        writer.addHeaderAlias("createdAt", "兑换时间");
        writer.setOnlyAlias(true);
        writer.write(scoreExchangeFansVOIPage);
        // 转文件流返回前端
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
            writer.flush(out);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("文件输出异常");
        } finally {
            writer.close();
            IoUtil.close(out);
        }
    }

    /**
     * 上下架
     *
     * @param scoreExchangeId
     * @param isFlag
     * @return
     */
    public Boolean updateIsFlag(Long scoreExchangeId, Integer isFlag) {
        if (null == scoreExchangeId || null == isFlag) {
            throw new BizException("请求参数缺失！");
        }
        ScoreExchangeEntity scoreExchangeEntity = scoreExchangeMapper.selectById(scoreExchangeId);
        if (ObjectUtils.isEmpty(scoreExchangeEntity)) {
            throw new BizException("数据异常，请检查！");
        }
        if (Constants.AWARD.COUPON == scoreExchangeEntity.getAwardType() && 2 == isFlag) {
            activityService.checkCouponThirdParam(List.of(scoreExchangeEntity.getAwardId()));
        }
        return this.lambdaUpdate()
                .set(ScoreExchangeEntity::getIsFlag, isFlag)
                .eq(ScoreExchangeEntity::getScoreExchangeId, scoreExchangeId)
                .update();
    }

    /**
     * 更新
     *
     * @param dto
     */
    public void update(ScoreExchangeDTO dto) {
        if (ObjectUtils.isEmpty(dto) || ObjectUtils.isEmpty(dto.getScoreExchangeId()) || ObjectUtils.isEmpty(dto.getIsFlag())) {
            throw new BizException("参数缺失");
        }
        ScoreExchangeEntity scoreExchangeEntity = scoreExchangeMapper.selectById(dto.getScoreExchangeId());
        if (ObjectUtils.isEmpty(scoreExchangeEntity)) {
            throw new BizException("数据异常，请检查！");
        }
        if (Constants.AWARD.COUPON == scoreExchangeEntity.getAwardType() && 2 == dto.getIsFlag()) {
            activityService.checkCouponThirdParam(List.of(scoreExchangeEntity.getAwardId()));
        }
        ScoreExchangeEntity entity = BeanUtil.copyProperties(dto, ScoreExchangeEntity.class);
        boolean flag = updateById(entity);
        if (!flag) {
            throw new BizException("更新失败");
        }
    }

    /**
     * 商城兑换记录
     *
     * @return
     */
    public IPage<ScoreExchangeRecordVO> getExchangeList(IPage iPage, String awardType) {
        return scoreExchangeMapper.getExchangeList(iPage, awardType);
    }
}
